//
// Created by hamlet on 23-6-19.
//

#ifndef COMPILERS_SEM_H
#define COMPILERS_SEM_H

#include <vector>
#include "Token.h"
#include "Lex.h"
#include "Gram.h"
#include "Quad.h"

// 语义分析器 & 生成中间代码
class Sem {
public:
    const std::vector<std::string> &idList;  // 标识符表
    const std::vector<int> &valueIntList;  // 整形常数表
    const std::shared_ptr<Token> &root;  // 语法树根节点

    Sem(Lex &lex, Gram &gram);

    std::vector<Quad> quads;  // 四元式序列
    int curTmpIndex;
    std::vector<TokenType> idType;  // 变量类型表

    bool generate();  // 生成四元式
    void output() const;

    static void simplify(std::shared_ptr<Token> node);  // 将语法树简化为抽象语法树（消除全部带'的非终结符）

private:
    void genNode(const std::shared_ptr<Token> &node);

    static const std::unordered_map<QuadType, std::string> quadName;

    class ExcSem : public std::exception {
    public:
        explicit ExcSem(std::string desc);

        [[nodiscard]] const char *what() const noexcept override;

    protected:
        std::string desc_;

    };

    class ExcUndefinedVariable : public ExcSem {
    public:
        explicit ExcUndefinedVariable(const std::string &idName);
    };

    class ExcTypeMismatch : public ExcSem {
    public:
        explicit ExcTypeMismatch(TokenType expected, TokenType actual);
    };

};


#endif //COMPILERS_SEM_H
